package com.qd.panda.gas.station.base;

import com.cdqidi.exception.ApiException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qd.panda.gas.base.BaseHttpResponseDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestClientException;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 〈一句话功能简述〉<br>
 *
 * @author sjk
 * @create 2022-11-14 10:54
 * @since 1.0.0
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class BaseHttpResponseUtil {
    private static ObjectMapper objectMapper;

    @Autowired
    public BaseHttpResponseUtil(ObjectMapper objectMapper) {
        BaseHttpResponseUtil.objectMapper = objectMapper;
    }

    public static BaseHttpResponseDTO build(Supplier<ResponseEntity<String>> supplier, Function<JsonNode, ? extends BaseHttpResponseDTO> responseDTO) {
        return build(supplier, responseDTO, null);
    }

    public static BaseHttpResponseDTO build(Supplier<ResponseEntity<String>> supplier, Function<JsonNode, ? extends BaseHttpResponseDTO> responseDTO, List<Integer> successHttpStatusList) {
        try {
            final ResponseEntity<String> responseEntity = supplier.get();
            final HttpStatus statusCode = responseEntity.getStatusCode();
            final JsonNode body = Optional.ofNullable(responseEntity.getBody()).map(s -> {
                try {
                    return objectMapper.readTree(s);
                } catch (JsonProcessingException e) {
                    throw new ApiException(e);
                }
            }).orElse(null);
            final BaseHttpResponseDTO baseHttpResponseDTO = responseDTO.apply(body);
            if (isSuccess(statusCode, successHttpStatusList)) {
                buildException(baseHttpResponseDTO, successHttpStatusList);
                return baseHttpResponseDTO;
            } else {
                String msg = "code: " + statusCode.value();
                String message = Optional.ofNullable(baseHttpResponseDTO).map(BaseHttpResponseDTO::getErrMsg).orElse(null);
                if (null != message) {
                    msg += ",message: " + message;
                }
                throw new ApiException(msg);
            }
        } catch (ResourceAccessException e) {
            throw e;
        } catch (RestClientException e) {
            e.printStackTrace();
            String message = e.getMessage();
            if (StringUtils.hasLength(message)) {
                final int start = message.indexOf("{");
                final int end = message.indexOf("}");
                if (start != -1 && end != -1) {
                    message = message.substring(start, end + 1);
                    log.error("RestClientException,message = {}", message);
                    try {
                        final BaseHttpResponseDTO baseHttpResponseDTO = responseDTO.apply(objectMapper.readTree(message));
                        buildException(baseHttpResponseDTO,null);
                    } catch (JsonProcessingException ex) {
                        throw new ApiException(ex.getMessage());
                    }
                }
            }
            throw new ApiException(e.getMessage());
        }
    }

    private static boolean isSuccess(HttpStatus statusCode, List<Integer> successHttpStatusList) {
        if (null == successHttpStatusList || successHttpStatusList.isEmpty()) {
            return statusCode == HttpStatus.OK;
        }
        return successHttpStatusList.contains(statusCode.value());
    }

    private static void buildException(BaseHttpResponseDTO baseHttpResponseDTO, List<Integer> successHttpStatusList) {
        if (null != baseHttpResponseDTO && !baseHttpResponseDTO.isSuccess()) {
            if (null == successHttpStatusList || successHttpStatusList.isEmpty()) {
                if (!baseHttpResponseDTO.isSuccess()) {
                    throw new ApiException("异常信息,code: " + baseHttpResponseDTO.getErrCode() + ",message: " + baseHttpResponseDTO.getErrMsg());
                }
            } else {
                if (!successHttpStatusList.contains(baseHttpResponseDTO.getErrCode())) {
                    throw new ApiException("异常信息,code: " + baseHttpResponseDTO.getErrCode() + ",message: " + baseHttpResponseDTO.getErrMsg());
                }
            }
        }
    }
}